package com.config;

import com.bean.BeanA;
import com.bean.BeanB;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 故意配置为循环依赖的情况
 * <p>
 * 具体的依赖注入过程：
 * <p>
 * 1、创建 {@link BeanA}
 * <p>
 * 2、把尚未初始化完成的 {@link BeanA} 放入 {@link DefaultSingletonBeanRegistry#singletonFactories}中
 * <p>
 * {@link AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])}
 * <p>
 * 3、扫描 {@link Autowired} 标记的方法（ {@link BeanA#setBeanB(com.bean.BeanB)} ），
 * 并从 {@link BeanFactory} 中寻找依赖的 {@link BeanB} 来进行依赖注入
 * <p>
 * 4、创建 {@link BeanB}
 * <p>
 * 5、扫描 {@link Autowired} 标记的方法（ {@link BeanB#setBeanA(com.bean.BeanA)} ），
 * 并从 {@link BeanFactory} 中寻找依赖的 {@link BeanA} 来进行依赖注入
 * <p>
 * {@link AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition, BeanWrapper)}
 * <p>
 * 6、从 {@link DefaultSingletonBeanRegistry#singletonFactories} 获取尚未初始化完成的 {@link BeanA}
 * {@link DefaultSingletonBeanRegistry#getSingleton(String, boolean)}
 * <p>
 * 7、（可选）为 {@link BeanA} 创建AOP 代理
 * <p>
 * 7.1、删除 {@link DefaultSingletonBeanRegistry#singletonFactories} 中的 {@link BeanA}
 * <p>
 * 7.2、把经过AOP代理的 {@link BeanA} 加入到 {@link DefaultSingletonBeanRegistry#earlySingletonObjects} 中
 * <p>
 * 8、把有代理但未初始化完成的 {@link BeanA} 注入到 {@link BeanB} 中
 * <p>
 * {@link AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject(Object, String, PropertyValues)}
 * <p>
 * 9、继续 {@link BeanB} 后续的初始化
 * <p>
 * {@link AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)}
 * <p>
 * 10、返回 {@link BeanA}的属性注入流程
 * <p>
 * {@link DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter)}
 * <p>
 * 11、把 {@link BeanB} 注入到 {@link BeanA} 中
 * <p>
 * 12、 {@link BeanA} 继续完成初始化操作
 */
@Configuration
public class LoopDependentConfig {


    @Bean
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB();
    }

}
